#pragma once
#ifndef NDFrame_H
#define NDFrame_H

#include "ZDataBase.h"

namespace NDFrame {
    template<typename StringType>
    class ZDFrame_API ZDataView;

    template<typename StringType, typename T>
    class ZDFrame_API ColView;

    template<typename StringType>
    class ZDFrame_API ZDataFrame : public ZDataBase<StringType> {
    public:
        using ItemType = DataItem<StringType>;
        using FieldInt = ColView<StringType, int>;
        using FieldStr = ColView<StringType, StringType>;
        using VecItemPtr = std::vector<DataItem<StringType> *>;
        using CharType = typename StringType::value_type;
        using RegexType = typename std::conditional<std::is_same<StringType, std::string>::value, std::regex, std::wregex>::type;
        using VecRegex = std::vector<RegexType>;

        explicit ZDataFrame(size_t capacity){
            this->m_capacity = capacity;
            allocate(capacity);
        }

        ZDataFrame(std::initializer_list<ItemType> items){
            this->m_size = items.size();
            this->m_capacity = this->m_size;
            allocate(this->m_capacity);
            std::copy(items.begin(), items.end(), this->ItemPtr.get());
        }

        ZDataFrame(int idx, int x0, int y0, int x1, int y1, int width, int height, StringType text,
                   StringType text_sep){
            this->m_size = 1;
            this->m_capacity = 1;
            allocate(this->m_capacity);
            this->ItemPtr.get()[0] = ItemType(idx, x0, y0, x1, y1, width, height, std::move(text), std::move(text_sep));
        }

        ZDataFrame(const ZDataFrame &other)                                             /* 复制构造函数 */
        {
            allocate(this->m_capacity);
            this->m_size = other.m_size;
            this->m_capacity = other.m_capacity;
            std::copy(other.ItemPtr.get(), other.ItemPtr.get() + other.m_size, this->ItemPtr.get());
        }


        ZDataFrame(ZDataFrame &&other) noexcept                                         /* 移动构造函数 */
        {
            this->ItemPtr = std::move(other.ItemPtr);
            this->m_size = other.m_size;
            this->m_capacity = other.m_capacity;
            other.m_size = 0;
            other.m_capacity = 0;
        }

        ~ZDataFrame() { deallocate(); };

        ZDataFrame &operator=(const ZDataFrame &other);                                 /* 复制赋值运算符 */
        ZDataFrame &operator=(ZDataFrame &&other) noexcept;                             /* 移动赋值运算符 */
        MAYBE_USE ZDataFrame clone() const { return ZDataFrame{*this}; };               /* 克隆函数      */
        MAYBE_USE size_t size() const override { return this->m_size; };
        VOID_USE void set_size(size_t size) { this->m_size = size; };

        MAYBE_USE bool empty() const override { return this->m_size == 0; };

        MAYBE_USE ItemType *getItemPtr() const override { return this->ItemPtr.get(); }

        MAYBE_USE size_t capacity() const { return this->m_capacity; };

        VOID_USE void push_back(const ItemType &item){
            if (this->m_size == this->m_capacity) {
                reserve(this->m_capacity == 0 ? 1 : this->m_capacity * 2);
            }
            this->ItemPtr.get()[this->m_size++] = item;
        }

        VOID_USE void push_back(ItemType &&item){
            if (this->m_size == this->m_capacity) {
                reserve(this->m_capacity == 0 ? 1 : this->m_capacity * 2);
            }
            this->ItemPtr.get()[this->m_size++] = std::move(item);
        }

        const ItemType &operator[](size_t index) const{
            if (index >= this->m_size) {
                throw std::out_of_range("Index out of range");
            }
            return this->ItemPtr.get()[index];
        }

        void reserve(size_t new_capacity);

        ItemType &back() override {
            if (this->empty()) {
                throw std::out_of_range("ZDataFrame is empty");
            }
            return this->ItemPtr.get()[this->m_size - 1];
        }

        ItemType &front() override{
            if (this->empty()) {
                throw std::out_of_range("ZDataFrame is empty");
            }
            return this->ItemPtr.get()[0];
        }

        VOID_USE void print() const override{
            ZDataBase<StringType>::print_data(*this);
        }

        //template<typename T>
        //ColView<StringType, T> field(T ItemType::* member) const {
        //    return ColView<StringType, T>(*this, member);
        //}

        ColView<StringType, int> field(int ItemType::* member) const override {
            return ColView<StringType, int>(*this, member);
        }

        ColView<StringType, StringType> field(StringType ItemType::* member) const override {
            return ColView<StringType, StringType>(*this, member);
        }

        MAYBE_USE inline static bool matches_regex(const StringType &text, const RegexType &regex_) {
            return std::regex_search(text, regex_);
        }

        MAYBE_USE FieldInt X0() const override { return this->field(&ItemType::x0); }

        MAYBE_USE FieldInt X1() const override { return this->field(&ItemType::x1); }

        MAYBE_USE FieldInt Y0() const override { return this->field(&ItemType::y0); }

        MAYBE_USE FieldInt Y1() const override { return this->field(&ItemType::y1); }

        MAYBE_USE FieldInt Width() const override { return this->field(&ItemType::width); }

        MAYBE_USE FieldInt Height() const override { return this->field(&ItemType::height); }

        MAYBE_USE FieldStr Text() const override { return this->field(&ItemType::text); }

        MAYBE_USE FieldStr Text_sep() const override { return this->field(&ItemType::text_sep); }

    private:
        size_t m_size = 0;
        size_t m_capacity = 0;
        std::shared_ptr<ItemType[]> ItemPtr;

        void allocate(size_t new_capacity){
            this->ItemPtr = std::shared_ptr<ItemType[]>(new ItemType[new_capacity], std::default_delete<ItemType[]>());
            this->m_capacity = new_capacity;
        }

        void deallocate(){
            this->ItemPtr.reset();
            this->m_size = 0;
            this->m_capacity = 0;
        }

    public:

        /*
        *  sort_values 依据提供的字段对整个ZDataFrame进行排序
        */
        void sort_values(Field field_, bool descending = false);

        /*
        *  merge_line    对ZDataFrame进行合并行
        *  合并条件：      限定宽(width)与高(height)， （下一行的x0与本行的x1的绝对距离小于width)，(下一行的y0与本行的y0的绝对距离小于height)
        *  符合合并条件的： 将本行与下一行text使用sep字符进行合并，(x0,y0)取这两行最小值,(x1,y1,height)取这两行最小大值, 并删除下一行
        *  再次递归本函数
        */
        MAYBE_USE ZDataFrame DF_merge_line(int width, int height, StringType &&sep = StringType());

        /*
        * 一般对筛选的子ZDataFrame进行重置index
        * reset_index()       直接对整个ZDataFrame进行重置索引（无复制）
        */
        VOID_USE void reset_index();

        /*
        * DF_indices_to_df(std::vector<size_t>& indices)     创建一个由提供索引的新ZDataFrame(深复制)
        * DF_pointers_to_df(VecItemPtr& pointers)创建一个由提供指针的新ZDataFrame(深复制)
        */
        MAYBE_USE ZDataFrame DF_indices_to_df(const std::vector<size_t> &indices) const;

        MAYBE_USE ZDataFrame DF_pointers_to_df(const VecItemPtr &pointers) const;

        MAYBE_USE ZDataFrame indices_to_df(const std::vector<size_t> &indices) const {
            return DF_indices_to_df(indices);
        }

        MAYBE_USE ZDataFrame pointers_to_df(const VecItemPtr &pointers) const {
            return DF_pointers_to_df(pointers);
        }

        /*
        * DF_drop_indice  删除 std::vector<size_t>&     indices其中的索引,返回删除后的ZDataFrame(深复制)
        * DF_drop_pointer 删除 std::vector<ItemType*>& pointers其中的指针,返回删除后的ZDataFrame(深复制)
        * drop_indice     删除 std::vector<size_t>&     indices其中的索引,就地删除
        * drop_pointer    删除 std::vector<ItemType*>& pointers其中的指针,就地删除
        */
        MAYBE_USE ZDataFrame DF_drop_indice(const std::vector<size_t> &indices) const;

        MAYBE_USE ZDataFrame DF_drop_pointer(const VecItemPtr &pointers) const;

        VOID_USE void drop_indice(const std::vector<size_t> &indices, bool inplace = true);

        VOID_USE void drop_pointer(const VecItemPtr &pointers);

        /*
        * drop_duplicates 删除重复行（就地修改原始的数据)
        * 使用默认值，即为空时，删除整行相同的后面一些行
        * field=text时，删除行中text相同的后面一些行
        */
        VOID_USE void drop_duplicates(Field field_);


        /*
        *   判断ZDataFrame的text字段是否在field字符串集合中
        *   - 返回值：
        *     std::vector<size_t>& indices     返回符合条件的索引
        *     VecItemPtr& pointers 返回符合条件的ZDataFrame的行指针
        *     ZDataFrame& dataframe            返回符合条件的ZDataFrame(深复制)
        */
        MAYBE_USE bool isin(const std::vector<StringType> &field, std::vector<size_t> &indices) const override{
            indices.clear();
            for (size_t i = 0; i < this->m_size; ++i) {
                if (std::find(field.begin(), field.end(), this->ItemPtr.get()[i].text) != field.end()) {
                    indices.push_back(this->ItemPtr.get()[i].idx);
                }
            }
            return !indices.empty();
        }

        MAYBE_USE bool isin(const std::vector<StringType> &field, VecItemPtr &pointers) const override{
            pointers.clear();
            for (size_t i = 0; i < this->m_size; ++i) {
                if (std::find(field.begin(), field.end(), this->ItemPtr.get()[i].text) != field.end()) {
                    pointers.push_back(&this->ItemPtr.get()[i]);
                }
            }
            return !pointers.empty();
        }

        MAYBE_USE bool isin(const std::vector<StringType> &field, ZDataFrame &dataframe) const;


        /*
        * 仿照python的join函数
        * 默认为空字符串
        * join_replace对ZDataFrame的text合并后的字符串中的字符进行替换
        * const StringType& Char_为分隔符
        */
        MAYBE_USE StringType join(Field field_, const StringType &Char_ = StringType()) const;

        MAYBE_USE StringType join_replace(Field field_,
                                          CharType oldChar,
                                          const StringType& newChar) const override {
            if (this->empty() || static_cast<int>(this->size()) < 2 || newChar.size() >= 2) {
                return {};
            }
            std::function<const StringType &(const ItemType &)> getField;
            if (field_ == Field::TEXT) {
                getField = [](const ItemType &item) -> const StringType & { return item.text; };
            } else if (field_ == Field::TEXT_SEP) {
                getField = [](const ItemType &item) -> const StringType & { return item.text_sep; };
            }

            std::basic_ostringstream<CharType> oss;
            for (size_t i = 0; i < this->m_size; ++i) {
                for (auto c: getField(this->ItemPtr.get()[i])) {
                    if (c == oldChar) {
                        oss << newChar.c_str();
                    } else {
                        oss << c;
                    }
                }
            }
            return oss.str();
        }

        MAYBE_USE StringType join_replace(Field field_,
                                          CharType oldChar,
                                          CharType newChar,
                                          const StringType &Char_ = StringType()) const;

        MAYBE_USE StringType join_replace2(Field field_,
                                           CharType oldChar0,
                                           CharType newChar0,
                                           CharType oldChar1,
                                           CharType newChar1,
                                           const StringType &Char_ = StringType()) const;

        /*
        * 对ZDataFrame的text中的字符进行替换放到text或者text_sep字段中
        * replace_df_text       替换单个字符
        * multi_replace_df_text 替换多个字符
        */
        VOID_USE void replace(Field txt, CharType oldChar, CharType newChar);

        VOID_USE void replace(Field txt, CharType oldChar0, CharType newChar0, CharType oldChar1, CharType newChar1);

        VOID_USE void multi_replace(Field txt, const std::map<StringType, StringType> &replacements);

        VOID_USE void multi_replace(Field txt, const std::unordered_map<StringType, StringType> &replacements);


        /*
        * 对ZDataFrame进行过滤（通用函数：传入lambda函数）
        * filter_ptr          返回符合条件的行地址
        */
        MAYBE_USE bool filter(const std::function<bool(const ItemType &)> &predicate, VecItemPtr &out_pointer) const;

        MAYBE_USE ZDataFrame DF_filter(const std::function<bool(const ItemType &)> &predicate) const;


        /*
        * 对ZDataFrame进行过滤（具体过滤函数：传入Field：（TEXT,TEXT_SEP）, 以及筛选条件） 返回符合条件的ZDataFrame(深复制)
        * loc_regex                 返回符合条件的ZDataFrame
        * loc_[regex,_xyxy]         返回符合条件的ZDataFrame, 筛选条件[regex, (>x0,y0; <x1,y1)]
        * loc_[regex,_x0x1]         返回符合条件的ZDataFrame, 筛选条件[regex, (>x0; <x1)]
        * loc_[regex,_y0y1]         返回符合条件的ZDataFrame, 筛选条件[regex, (>y0; <y1)]
        * loc_[regex,_x0y0]         返回符合条件的ZDataFrame, 筛选条件[regex, (<x0; <y0)]
        * loc_[regex,_x1y1]         返回符合条件的ZDataFrame, 筛选条件[regex, (>x1; >y1)]
        */
        MAYBE_USE ZDataFrame DF_loc_regex(Field field, const RegexType &regex_) const {
            return DF_reg_impl(field, VecRegex{regex_});
        }

        MAYBE_USE ZDataFrame DF_loc_regex(Field field, const VecRegex &regex_) const {
            return DF_reg_impl(field, regex_);
        }

        MAYBE_USE ZDataFrame DF_loc_regex_grate_strlen(Field field, const RegexType &regex_, int len) const {
            return DF_reg_common4(field, VecRegex{regex_}, len, std::greater<>());
        }

        MAYBE_USE ZDataFrame DF_loc_regex_equal_strlen(Field field, const RegexType &regex_, int len) const {
            return DF_reg_common4(field, VecRegex{regex_}, len, std::equal_to<>());
        }

        MAYBE_USE ZDataFrame DF_loc_regex_less_strlen(Field field, const RegexType &regex_, int len) const {
            return DF_reg_common4(field, VecRegex{regex_}, len, std::less<>());
        }

        MAYBE_USE ZDataFrame DF_loc_regex_grate_strlen(Field field, const VecRegex &regex_, int len) const {
            return DF_reg_common4(field, regex_, len, std::greater<>());
        }

        MAYBE_USE ZDataFrame DF_loc_regex_equal_strlen(Field field, const VecRegex &regex_, int len) const {
            return DF_reg_common4(field, regex_, len, std::equal_to<>());
        }

        MAYBE_USE ZDataFrame DF_loc_regex_less_strlen(Field field, const VecRegex &regex_, int len) const {
            return DF_reg_common4(field, regex_, len, std::less<>());
        }

        MAYBE_USE ZDataFrame
        DF_loc_regex_xyxy(Field field, const RegexType &regex_, int x0, int y0, int x1, int y1) const {
            return DF_reg_common3(field, VecRegex{regex_},
                                  [x0, y0, x1, y1](const ItemType &item) {
                                      return item.x0 > x0 && item.x1 < x1 && item.y0 > y0 && item.y1 < y1;
                                  });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x0x1(Field field, const RegexType &regex_, int x0, int x1) const {
            return DF_reg_common3(field, VecRegex{regex_},
                                  [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_y0y1(Field field, const RegexType &regex_, int y0, int y1) const {
            return DF_reg_common3(field, VecRegex{regex_},
                                  [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x0y0(Field field, const RegexType &regex_, int x0, int y0) const {
            return DF_reg_common3(field, VecRegex{regex_},
                                  [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x1y1(Field field, const RegexType &regex_, int x1, int y1) const {
            return DF_reg_common3(field, VecRegex{regex_},
                                  [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x0x1(Field field, const VecRegex &regex_, int x0, int x1) const {
            return DF_reg_common3(field, regex_,
                                  [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_y0y1(Field field, const VecRegex &regex_, int y0, int y1) const {
            return DF_reg_common3(field, regex_,
                                  [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x0y0(Field field, const VecRegex &regex_, int x0, int y0) const {
            return DF_reg_common3(field, regex_,
                                  [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataFrame DF_loc_regex_x1y1(Field field, const VecRegex &regex_, int x1, int y1) const {
            return DF_reg_common3(field, regex_,
                                  [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_xyxy(int x0, int y0, int x1, int y1) const {
            auto condition = [x0, y0, x1, y1](const ItemType &item) noexcept -> bool {
                return item.x0 > x0 && item.y0 > y0 && item.x1 < x1 && item.y1 < y1;
            };
            return DF_xyxy_impl(condition);
        }

        MAYBE_USE ZDataFrame DF_loc_x0x1(int x0, int x1) const {
            return DF_xyxy_impl([x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataFrame DF_loc_y0y1(int y0, int y1) const {
            return DF_xyxy_impl([y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_x0y0(int x0, int y0) const {
            return DF_xyxy_impl([x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataFrame DF_loc_x1y1(int x1, int y1) const {
            return DF_xyxy_impl([x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE ZDataFrame DF_loc_x0(int x0) const {
            return DF_xyxy_impl([x0](const ItemType &item) { return item.x0 > x0; });
        }

        MAYBE_USE ZDataFrame DF_loc_y0(int y0) const {
            return DF_xyxy_impl([y0](const ItemType &item) { return item.y0 > y0; });
        }

        MAYBE_USE ZDataFrame DF_loc_x1(int x1) const {
            return DF_xyxy_impl([x1](const ItemType &item) { return item.x1 < x1; });
        }

        MAYBE_USE ZDataFrame DF_loc_y1(int y1) const {
            return DF_xyxy_impl([y1](const ItemType &item) { return item.y1 < y1; });
        }


        /*
        * 对ZDataFrame进行过滤（具体过滤函数：传入Field：（TEXT,TEXT_SEP）, 以及筛选条件） 返回符合条件的地址
        * loc_regex             返回查找值是否为空, 第一个参数为筛选【DataItem的地址】
        * loc_[regex,_xyxy]     返回查找值是否为空, 第一个参数为筛选【DataItem的地址】,筛选条件[regex, (>x0,y0; <x1,y1)]
        * loc_[regex,_x0x1]     返回查找值是否为空, 第一个参数为筛选【DataItem的地址】,筛选条件[regex, (>x0; <x1)]
        * loc_[regex,_y0y1]     返回查找值是否为空, 第一个参数为筛选【DataItem的地址】,筛选条件[regex, (>y0; <y1)]
        * loc_[regex,_x0y0]     返回查找值是否为空, 第一个参数为筛选【DataItem的地址】,筛选条件[regex, (<x0; <y0)]
        * loc_[regex,_x1y1]     返回查找值是否为空, 第一个参数为筛选【DataItem的地址】,筛选条件[regex, (>x1; >y1)]
        */

        MAYBE_USE bool loc_regex(VecItemPtr &out_ptr, Field field, const RegexType &regex_) const {
            return ptr_reg_impl(out_ptr, field, VecRegex{regex_});
        }

        MAYBE_USE bool loc_regex(VecItemPtr &out_ptr, Field field, const VecRegex &regex_) const {
            return ptr_reg_impl(out_ptr, field, regex_);
        }

        MAYBE_USE bool
        loc_regex_grate_strlen(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, VecRegex{regex_}, len, std::greater<>());
        }

        MAYBE_USE bool
        loc_regex_equal_strlen(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, VecRegex{regex_}, len, std::equal_to<>());
        }

        MAYBE_USE bool loc_regex_less_strlen(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, VecRegex{regex_}, len, std::less<>());
        }

        MAYBE_USE bool loc_regex_grate_strlen(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, regex_, len, std::greater<>());
        }

        MAYBE_USE bool loc_regex_equal_strlen(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, regex_, len, std::equal_to<>());
        }

        MAYBE_USE bool loc_regex_less_strlen(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int len) const {
            return ptr_reg_common5(out_ptr, field, regex_, len, std::less<>());
        }


        MAYBE_USE bool loc_regex_xyxy(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int x0, int y0, int x1,
                                      int y1) const {
            return ptr_reg_common4(out_ptr, field, VecRegex{regex_}, [x0, y0, x1, y1](const ItemType &item) {
                return item.x0 > x0 && item.x1 < x1 && item.y0 > y0 && item.y1 < y1;
            });
        }


        MAYBE_USE bool loc_regex_x0x1(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int x0, int x1) const {
            return ptr_reg_common4(out_ptr, field, VecRegex{regex_},
                                   [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE bool loc_regex_y0y1(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int y0, int y1) const {
            return ptr_reg_common4(out_ptr, field, VecRegex{regex_},
                                   [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE bool loc_regex_x0y0(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int x0, int y0) const {
            return ptr_reg_common4(out_ptr, field, VecRegex{regex_},
                                   [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE bool loc_regex_x1y1(VecItemPtr &out_ptr, Field field, const RegexType &regex_, int x1, int y1) const {
            return ptr_reg_common4(out_ptr, field, VecRegex{regex_},
                                   [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE bool loc_regex_x0x1(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int x0, int x1) const {
            return ptr_reg_common4(out_ptr, field, regex_,
                                   [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE bool loc_regex_y0y1(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int y0, int y1) const {
            return ptr_reg_common4(out_ptr, field, regex_,
                                   [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE bool loc_regex_x0y0(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int x0, int y0) const {
            return ptr_reg_common4(out_ptr, field, regex_,
                                   [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE bool loc_regex_x1y1(VecItemPtr &out_ptr, Field field, const VecRegex &regex_, int x1, int y1) const {
            return ptr_reg_common4(out_ptr, field, regex_,
                                   [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE bool loc_xyxy(VecItemPtr &out_ptr, int x0, int y0, int x1, int y1) const {
            auto condition = [x0, y0, x1, y1](const ItemType &item) -> bool {
                return item.x0 > x0 && item.y0 > y0 && item.x1 < x1 && item.y1 < y1;
            };
            return ptr_xyxy(out_ptr, condition);
        }

        MAYBE_USE bool loc_x0x1(VecItemPtr &out_ptr, int x0, int x1) const {
            return ptr_xyxy(out_ptr, [x0, x1](const ItemType &item) {
                return item.x0 > x0 && item.x1 < x1;
            });
        }

        MAYBE_USE bool loc_y0y1(VecItemPtr &out_ptr, int y0, int y1) const {
            return ptr_xyxy(out_ptr, [y0, y1](const ItemType &item) {
                return item.y0 > y0 && item.y1 < y1;
            });
        }

        MAYBE_USE bool loc_x0y0(VecItemPtr &out_ptr, int x0, int y0) const {
            return ptr_xyxy(out_ptr, [x0, y0](const ItemType &item) {
                return item.x0 > x0 && item.y0 > y0;
            });
        }

        MAYBE_USE bool loc_x1y1(VecItemPtr &out_ptr, int x1, int y1) const {
            return ptr_xyxy(out_ptr, [x1, y1](const ItemType &item) {
                return item.x1 < x1 && item.y1 < y1;
            });
        }

        MAYBE_USE bool loc_x0(VecItemPtr &out_ptr, int x0) const {
            return ptr_xyxy(out_ptr, [x0](const ItemType &item) { return item.x0 < x0; });
        }

        MAYBE_USE bool loc_y0(VecItemPtr &out_ptr, int y0) const {
            return ptr_xyxy(out_ptr, [y0](const ItemType &item) { return item.y0 < y0; });
        }

        MAYBE_USE bool loc_x1(VecItemPtr &out_ptr, int x1) const {
            return ptr_xyxy(out_ptr, [x1](const ItemType &item) { return item.x1 > x1; });
        }

        MAYBE_USE bool loc_y1(VecItemPtr &out_ptr, int y1) const {
            return ptr_xyxy(out_ptr, [y1](const ItemType &item) { return item.y1 > y1; });
        }

        /*
        * 对ZDataFrame  进行索引筛选(默认索引按顺序排列)
        * DF_iloc       返回符合条件的行索引[0,2)的复制ZDataFrame类,前闭后开
        * DV_iloc       返回符合条件的行索引[0,2)的视图ZDataView类,前闭后开
        * iloc          返回符合条件的行地址[0,2),前闭后开
        */
        MAYBE_USE ZDataFrame<StringType> DF_iloc(int idx0, int idx1) const;

        MAYBE_USE ZDataView<StringType> DV_iloc(int idx0, int idx1) const {
            return ZDataView{*this, static_cast<size_t>(idx0), static_cast<size_t>(idx1)};
        }

        MAYBE_USE bool iloc(VecItemPtr &out_ptr, int idx0, int idx1) const;

        /*
        * 对ZDataFrame进行过滤（具体过滤函数：传入具体数值）
        * - 输入 Field field_
        * - 输入 const VecRegex& regex_, int x0, int y0, int x1, int y1
        * - 返回值(符合条件的视图)：ZDataView<StringType>
        */
        MAYBE_USE ZDataView<StringType> DV_loc_regex(Field field, const RegexType &regex_) const {
            return dv_reg_impl(field, VecRegex{regex_});
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex(Field field, const VecRegex &regex_) const {
            return dv_reg_impl(field, regex_);
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_grate_strlen(Field field, const VecRegex &regex_, int len) const {
            return dv_reg_common4(field, regex_, len, std::greater<>());
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_equal_strlen(Field field, const VecRegex &regex_, int len) const {
            return dv_reg_common4(field, regex_, len, std::equal_to<>());
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_less_strlen(Field field, const VecRegex &regex_, int len) const {
            return dv_reg_common4(field, regex_, len, std::less<>());
        }


        MAYBE_USE ZDataView<StringType> DV_loc_regex_grate_strlen(Field field, const RegexType &regex_, int len) const {
            return dv_reg_common4(field, VecRegex{regex_}, len, std::greater<>());
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_equal_strlen(Field field, const RegexType &regex_, int len) const {
            return dv_reg_common4(field, VecRegex{regex_}, len, std::equal_to<>());
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_less_strlen(Field field, const RegexType &regex_, int len) const {
            return dv_reg_common4(field, VecRegex{regex_}, len, std::less<>());
        }

        MAYBE_USE ZDataView<StringType>
        DV_loc_regex_xyxy(Field field, const VecRegex &regex_, int x0, int y0, int x1, int y1) const {
            return dv_reg_common3(field, regex_, [x0, y0, x1, y1](const ItemType &item) {
                return item.x0 > x0 && item.x1 < x1 && item.y0 > y0 && item.y1 < y1;
            });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x0x1(Field field, const VecRegex &regex_, int x0, int x1) const {
            return dv_reg_common3(field, regex_,
                                  [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_y0y1(Field field, const VecRegex &regex_, int y0, int y1) const {
            return dv_reg_common3(field, regex_,
                                  [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x0y0(Field field, const VecRegex &regex_, int x0, int y0) const {
            return dv_reg_common3(field, regex_,
                                  [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x1y1(Field field, const VecRegex &regex_, int x1, int y1) const {
            return dv_reg_common3(field, regex_,
                                  [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x0x1(Field field, const RegexType &regex_, int x0, int x1) const {
            return dv_reg_common3(field, VecRegex{regex_},
                                  [x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_y0y1(Field field, const RegexType &regex_, int y0, int y1) const {
            return dv_reg_common3(field, VecRegex{regex_},
                                  [y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x0y0(Field field, const RegexType &regex_, int x0, int y0) const {
            return dv_reg_common3(field, VecRegex{regex_},
                                  [x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_regex_x1y1(Field field, const RegexType &regex_, int x1, int y1) const {
            return dv_reg_common3(field, VecRegex{regex_},
                                  [x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }


        MAYBE_USE ZDataView<StringType> DV_loc_xyxy(int x0, int y0, int x1, int y1) const {
            return DV_loc([x0, y0, x1, y1](const ItemType &item) {
                return item.x0 > x0 && item.y0 > y0 && item.x1 < x1 && item.y1 < y1;
            });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_x0x1(int x0, int x1) const {
            return DV_loc([x0, x1](const ItemType &item) { return item.x0 > x0 && item.x1 < x1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_y0y1(int y0, int y1) const {
            return DV_loc([y0, y1](const ItemType &item) { return item.y0 > y0 && item.y1 < y1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_x0y0(int x0, int y0) const {
            return DV_loc([x0, y0](const ItemType &item) { return item.x0 > x0 && item.y0 > y0; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_x1y1(int x1, int y1) const {
            return DV_loc([x1, y1](const ItemType &item) { return item.x1 < x1 && item.y1 < y1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_x0(int x0) const {
            return DV_loc([x0](const ItemType &item) { return item.x0 < x0; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_x1(int x1) const {
            return DV_loc([x1](const ItemType &item) { return item.x1 > x1; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_y0(int y0) const {
            return DV_loc([y0](const ItemType &item) { return item.y0 < y0; });
        }

        MAYBE_USE ZDataView<StringType> DV_loc_y1(int y1) const {
            return DV_loc([y1](const ItemType &item) { return item.y1 > y1; });
        }


    private:
        void drop_indice_inplace(const std::vector<size_t> &indices);

        ZDataFrame drop_indice_copy(const std::vector<size_t> &indices) const;

        ////////////////////////////////////////////////////////////////////////////////////////////////////

        template<typename MapType>
        void multi_replace_df_text_impl(Field txt, const MapType &replacements);

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        ZDataFrame DF_reg_impl(NDFrame::Field field, const VecRegex &regex_) const;

        ZDataFrame DF_xyxy_impl(const std::function<bool(const DataItem<StringType> &)> &condition) const;

        ZDataFrame DF_reg_common4(
                Field field,
                const VecRegex &regex_, int len,
                const std::function<bool(size_t, size_t)> &compare) const;

        ZDataFrame DF_reg_common3(
                NDFrame::Field field,
                const VecRegex &regex_,
                const std::function<bool(const DataItem<StringType> &)> &condition) const;

        //////////////////////////////////////////////////////////////////
        template<typename ConditionIdx>
        bool ptr_xyxy(VecItemPtr &out_indices, ConditionIdx conditionIdx) const;

        bool ptr_reg_impl(VecItemPtr &out_ptr, Field field, const VecRegex &regex_) const;


        bool ptr_reg_common5(
                VecItemPtr &out_ptr,
                NDFrame::Field field,
                const std::vector<RegexType> &regex_, int len,
                const std::function<bool(size_t, size_t)> &compare) const;

        bool ptr_reg_common4(
                VecItemPtr &out_indices,
                NDFrame::Field field,
                const std::vector<RegexType> &regex_,
                const std::function<bool(const ItemType &)> &condition) const;

        //////////////////////////////////////////////////////////////////
        template<typename ConditionInt>
        ZDataView<StringType> DV_loc(ConditionInt conditionInt) const;

        ZDataView<StringType> dv_reg_impl(Field field, const std::vector<RegexType> &regex_) const;

        ZDataView<StringType> dv_reg_common4(
                NDFrame::Field field,
                const std::vector<RegexType> &regex_, int len,
                const std::function<bool(size_t, size_t)> &compare) const;

        ZDataView<StringType> dv_reg_common3(
                NDFrame::Field field,
                const std::vector<RegexType> &regex_,
                const std::function<bool(const ItemType &)> &condition) const;
    };


};


#endif // !NDFrame_H
